package com.baomidou;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.builder.Controller;
import com.baomidou.mybatisplus.generator.config.builder.Entity;
import com.baomidou.mybatisplus.generator.config.builder.Mapper;
import com.baomidou.mybatisplus.generator.config.builder.Service;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.google.common.base.Strings;

import java.util.Collections;

public class GCPGenerator {

    private final GCPConfig gcpConfig;

    public GCPGenerator(GCPConfig gcpConfig) {
        this.gcpConfig = gcpConfig;
    }

    public void execute() {
        FastAutoGenerator.create(datasourceBuilder())
                .globalConfig(this::globalConfigBuilder)
                .packageConfig(this::packageConfigBuilder)
                .strategyConfig(this::strategyConfigBuilder)
                .templateConfig(this::templateConfigBuilder)
                .execute();
    }

    public DataSourceConfig.Builder datasourceBuilder() {
        return new DataSourceConfig.Builder(gcpConfig.getDbUrl(), gcpConfig.getUsername(), gcpConfig.getPassword())
                .typeConvertHandler(new CustomizedMSSQLTypeHandler());
    }

    public void globalConfigBuilder(GlobalConfig.Builder builder) {
        builder.outputDir(Constants.DEFAULT_JAVA_OUTPUT_DIR)
                .author(gcpConfig.getAuthor())
                // 只支持jdk8
                .dateType(DateType.TIME_PACK)
                // 不要打开代码生成目录
                .disableOpenDir();
    }

    public void packageConfigBuilder(PackageConfig.Builder builder) {
        builder
                .parent(gcpConfig.getRootPackage())
                .entity(Constants.PACKAGE_ENTITY)
                .mapper(Constants.PACKAGE_MAPPER)
                .service(Constants.PACKAGE_SERVICE)
                .serviceImpl(Constants.PACKAGE_SERVICE_IMPL)
                .controller(Constants.PACKAGE_CONTROLLER)
                .pathInfo(Collections.singletonMap(OutputFile.xml, Constants.DEFAULT_XML_OUTPUT_DIR));
    }

    public void strategyConfigBuilder(StrategyConfig.Builder builder) {
        builder.addInclude(gcpConfig.getIncludeTables())
                .addExclude(gcpConfig.getExcludeTables())
                .addTablePrefix(gcpConfig.getTablePrefixes())
                .addTableSuffix(gcpConfig.getTableSuffixes())
                .addFieldPrefix(gcpConfig.getFieldPrefixes())
                .addFieldSuffix(gcpConfig.getFieldSuffixes());
        // 以下是Entity相关配置
        // 置灰的强制不启用
        Entity.Builder entityBuilder = builder.entityBuilder();
        // 自定义继承的Entity类全称或者自定义继承的Entity类全称，带包名
        entityBuilder.superClass(gcpConfig.getSuperClassName())
                // 禁用生成serialVersionUID
                //.disableSerialVersionUID()
                // 开启生成字段常量
                .enableColumnConstant()
                // 开启链式模型
                .enableChainModel()
                // 开启lombok模型
                .enableLombok()
                // 开启Boolean类型字段移除is前缀
                //.enableRemoveIsPrefix()
                // 开启生成实体时生成字段注解
                .enableTableFieldAnnotation()
                // 开启 ActiveRecord 模式
                //.enableActiveRecord()
                // 设置乐观锁数据库表字段名称
                .versionColumnName(gcpConfig.getFieldVersion())
                // 设置乐观锁实体属性字段名称
                //.versionPropertyName(String versionPropertyName)
                // 逻辑删除数据库字段名称
                .logicDeleteColumnName(gcpConfig.getFieldLogicDelete())
                // 逻辑删除实体属性名称
                //.logicDeletePropertyName(String logicDeletePropertyName)
                // 数据库表映射到实体的命名策略
                .naming(NamingStrategy.underline_to_camel)
                // 数据库表字段映射到实体的命名策略
                .columnNaming(NamingStrategy.underline_to_camel)
                // 添加父类公共字段
                //.addSuperEntityColumns(String... superEntityColumns)
                // 添加忽略字段
                .addIgnoreColumns(gcpConfig.getIgnoreColumns())
                // 指定生成的主键的ID类型
                .idType(IdType.ASSIGN_ID)
                .enableFileOverride()
                // 格式化文件名称
                .formatFileName(Constants.FILENAME_ENTITY);
        // 以下是mapper相关配置
        Mapper.Builder mapperBuilder = builder.mapperBuilder();
        mapperBuilder.enableBaseResultMap()
                .enableBaseColumnList()
                .enableMapperAnnotation()
                .enableFileOverride()
                .formatMapperFileName(Constants.FILENAME_MAPPER)
                .formatXmlFileName(Constants.FILENAME_XML);
        // 以下是service相关配置
        Service.Builder serviceBuilder = builder.serviceBuilder();
        serviceBuilder.enableFileOverride()
                .formatServiceFileName(Constants.FILENAME_SERVICE)
                .formatServiceImplFileName(Constants.FILENAME_SERVICE_IMPL);
        if (!Strings.isNullOrEmpty(gcpConfig.getSuperServiceImplClass())) {
            serviceBuilder.superServiceImplClass(gcpConfig.getSuperServiceImplClass());
        }
        // 以下是controller相关配置
        Controller.Builder controllerBuilder = builder.controllerBuilder();
        controllerBuilder.enableFileOverride()
                .enableRestStyle()
                .enableHyphenStyle()
                .formatFileName(Constants.FILENAME_CONTROLLER);
    }

    public void templateConfigBuilder(TemplateConfig.Builder builder) {
        builder.disable(TemplateType.CONTROLLER)
                .controller(Constants.TEMPLATE_CONTROLLER)
                .build();
    }
}
